// Package main implements a server for Greeter service.
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net"
	"sync"
	"time"

	grpc_trace "github.com/aoliang/go2sky-plugins/grpc"
	"google.golang.org/grpc"

	pb "gitee.com/aoliang/trace/skywalking/grpc/proto"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.Name)
	time.Sleep(time.Duration(100+rand.Intn(200)) * time.Millisecond)
	r, err := getDemoServerClient().SayHello(ctx, &pb.HelloRequest{Name: in.Name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.Message)
	time.Sleep(time.Duration(100+rand.Intn(200)) * time.Millisecond)
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func (s *server) SayStreamHello(stream pb.Greeter_SayStreamHelloServer) error {
	for {
		in, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}

		l := rand.Intn(3) + 1
		for i := 0; i < l; i++ {
			if err := stream.Send(&pb.HelloReply{Message: fmt.Sprintf("hello %s", in.Name)}); err != nil {
				return err
			}
		}
	}
}

var (
	client pb.GreeterClient
	m      sync.Mutex
)

func getDemoServerClient() pb.GreeterClient {
	if client != nil {
		return client
	}
	m.Lock()
	defer m.Unlock()

	if client != nil {
		return client
	}

	traceInterceptor := grpc_trace.NewUnaryClientTraceInterceptor(getTracer("grpc-demo-alpha"))
	conn, err := grpc.Dial("localhost:50052", grpc.WithInsecure(), grpc.WithUnaryInterceptor(traceInterceptor))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	client = pb.NewGreeterClient(conn)
	return client
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	traceInterceptor := grpc_trace.NewUnaryServerTraceInterceptor(getTracer("grpc-demo-alpha"))
	s := grpc.NewServer(grpc.UnaryInterceptor(traceInterceptor))
	pb.RegisterGreeterServer(s, &server{})

	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
